package com.qlogic.commons.platform.impls.lucene.handler;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.eventfilesystem.POIFSReader;

public class POIExcelHandler extends MSOfficeHandler {

	/**
	 * Hide the public constructor.
	 * <p>
	 */
	public POIExcelHandler() {
	}

	/**
	 * @see org.jlibrary.core.search.extraction.Extractor#extractHeader(java.io.File)
	 */
	public HeaderMetaData extractHeader(File f) throws ContentHandlerException {

		try {
			POIFSReader reader = new POIFSReader();
			reader.registerListener(this);
			reader.read(getStreamCopy(new FileInputStream(f)));

			// extract all information
			return extractMetaInformation();
		} catch (Exception e) {
			throw new ContentHandlerException(e);
		}

	}

	public String getText(InputStream is, String encoding) throws ContentHandlerException {
		String result;
		try {
			result = extractTableContent(getStreamCopy (is));
		} catch (IOException e) {
			throw new ContentHandlerException (e);
		}
		return removeControlChars(result);
	}

	/**
	 * Extracts the text from the Excel table content.
	 * <p>
	 * 
	 * @param in
	 *            the document input stream
	 * @return the extracted text
	 * @throws IOException
	 *             if something goes wring
	 */
	protected String extractTableContent(InputStream in) throws IOException {

		HSSFWorkbook excelWb = new HSSFWorkbook(in);
		StringBuffer result = new StringBuffer(4096);

		int numberOfSheets = excelWb.getNumberOfSheets();

		for (int i = 0; i < numberOfSheets; i++) {
			HSSFSheet sheet = excelWb.getSheetAt(i);
			int numberOfRows = sheet.getPhysicalNumberOfRows();
			if (numberOfRows > 0) {

				if ((excelWb.getSheetName(i) != null)
						&& !excelWb.getSheetName(i).equals("")) {
					// append sheet name to content
					if (i > 0) {
						result.append("\n\n");
					}
					result.append(excelWb.getSheetName(i).trim());
					result.append(":\n\n");
				}

				Iterator rowIt = sheet.rowIterator();
				while (rowIt.hasNext()) {
					HSSFRow row = (HSSFRow) rowIt.next();
					if (row != null) {
						boolean hasContent = false;
						Iterator it = row.cellIterator();
						while (it.hasNext()) {
							HSSFCell cell = (HSSFCell) it.next();
							String text = null;
							try {
								switch (cell.getCellType()) {
								case HSSFCell.CELL_TYPE_BLANK:
								case HSSFCell.CELL_TYPE_ERROR:
									// ignore all blank or error cells
									break;
								case HSSFCell.CELL_TYPE_NUMERIC:
									text = Double.toString(cell
											.getNumericCellValue());
									break;
								case HSSFCell.CELL_TYPE_BOOLEAN:
									text = Boolean.toString(cell
											.getBooleanCellValue());
									break;
								case HSSFCell.CELL_TYPE_STRING:
								default:
									text = cell.getStringCellValue();
									break;
								}
							} catch (Exception e) {
								// ignore this cell
							}
							if ((text != null) && !text.equals("")) {
								result.append(text.trim());
								result.append(' ');
								hasContent = true;
							}
						}
						if (hasContent) {
							// append a newline at the end of each row that has
							// content
							result.append('\n');
						}
					}
				}
			}
		}

		return result.toString();
	}

	public Document getDocument(InputStream is, String encoding) throws ContentHandlerException {
		String bodyText = getText(is, encoding);
		if (bodyText != null) {
			Document doc = new Document();
			doc.add(new Field(BODY, bodyText, Field.Store.NO,
					Field.Index.TOKENIZED));
			return doc;
		}
		return null;
	}

}
